

#include <phApp_Init.h>
#include <phNfcLib_Int.h>
#include <phNfcLib_Initialization.h>

#include "Reader.h"

#define TagTypeMask(type)		(1u << type)

static inline int Reader_ISO14443_Verify(uint16_t tech){
	return PHAC_DISCLOOP_CHECK_ANDMASK(reader.wTagsDetected, tech);
}

static inline int Reader_ISO14443_4_Verify(void){
	if(!PHAC_DISCLOOP_CHECK_ANDMASK(reader.wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_A | PHAC_DISCLOOP_POS_BIT_MASK_B)){
		return 0;
	}
	
	switch(reader.dwActivatedType){
	case E_PH_NFCLIB_TYPEA_LAYER4:
	case E_PH_NFCLIB_TYPEB_LAYER4:
	case E_PH_NFCLIB_MIFARE_DESFIRE:
		return 1;
	default: break;
	}

	return 0;
}


int Reader_ISO14443A_GetATS(uint8_t* ats, uint8_t* alen){
	phacDiscLoop_Sw_DataParams_t *pDataParams = (phacDiscLoop_Sw_DataParams_t *)reader.pDiscLoop;
	if(!Reader_ISO14443_Verify(PHAC_DISCLOOP_POS_BIT_MASK_A)){
		return -1;
	}
	
	*alen = pDataParams->sTypeATargetInfo.sTypeA_I3P4.pAts[0];
	memcpy(ats, pDataParams->sTypeATargetInfo.sTypeA_I3P4.pAts, *alen);
	
	return 0;
}

int Reader_ISO14443B_GetATQB(uint8_t* atqb, uint8_t* alen){
	if(!Reader_ISO14443_Verify(PHAC_DISCLOOP_POS_BIT_MASK_B)){
		return -1;
	}
	phacDiscLoop_Sw_DataParams_t *pDataParams = (phacDiscLoop_Sw_DataParams_t *)reader.pDiscLoop;
	*alen = pDataParams->sTypeBTargetInfo.aTypeB_I3P3[0].bAtqBLength;
	memcpy(atqb, pDataParams->sTypeBTargetInfo.aTypeB_I3P3[0].aAtqB, *alen);
	
	return 0;
}

int Reader_ISO14443_4_CheckPresence(void){
//TODO:检测卡是否还在场
	if(!Reader_ISO14443_4_Verify()){
		return 0;
	}
	phStatus_t	wStatus = phpalI14443p4_PresCheck(&gphNfcLib_Params.spalI14443p4);
	if(wStatus == PH_ERR_SUCCESS){
		return 1;
	}
	
	return 0;
}


int Reader_ISO14443_4_Exchange(uint8_t* capdu, uint16_t clen, uint8_t *rapdu, uint16_t* rlen, uint16_t rsize){
	if(!Reader_ISO14443_4_Verify()){
		LOG_E("invalid!");
		return -3;
	}
	phStatus_t	wStatus = phpalI14443p4_Exchange(
		&gphNfcLib_Params.spalI14443p4,
		PH_EXCHANGE_DEFAULT,
		capdu,
		clen,
		&gphNfcLib_State.pRxBuffer,
		&gphNfcLib_State.wRxLength
		);
	if(wStatus){
		reader.dwActivatedType = E_PH_NFCLIB_UNKNOWN;
		LOG_E("error: %04X", wStatus);
		return -1;
	}
	if(gphNfcLib_State.wRxLength > rsize){
		LOG_E("Over flow!");
		return -2;
	}
	memcpy(rapdu, gphNfcLib_State.pRxBuffer, gphNfcLib_State.wRxLength);
	*rlen = gphNfcLib_State.wRxLength;
	return 0;
}


int Reader_ISO14443A_GetATQA(uint8_t atqa[/*2*/]){
	if(!Reader_ISO14443_Verify(PHAC_DISCLOOP_POS_BIT_MASK_A)){
		return -1;
	}
	phacDiscLoop_Sw_DataParams_t *pDataParams = (phacDiscLoop_Sw_DataParams_t *)reader.pDiscLoop;
	memcpy(atqa, pDataParams->sTypeATargetInfo.aTypeA_I3P3[0].aAtqa, 2);
	return 0;
}

int Reader_ISO14443A_GetSAK(uint8_t* sak){
	if(!Reader_ISO14443_Verify(PHAC_DISCLOOP_POS_BIT_MASK_A)){
		return -1;
	}
	phacDiscLoop_Sw_DataParams_t *pDataParams = (phacDiscLoop_Sw_DataParams_t *)reader.pDiscLoop;
	*sak = pDataParams->sTypeATargetInfo.aTypeA_I3P3[0].aSak;
	return 0;
}

int Reader_ISO14443B_GetAnswerToATTRIB(uint8_t* rattrib, uint8_t* rlen){
	if(!Reader_ISO14443_Verify(PHAC_DISCLOOP_POS_BIT_MASK_B)){
		return -1;
	}
		
	phacDiscLoop_Sw_DataParams_t *pDataParams = (phacDiscLoop_Sw_DataParams_t *)reader.pDiscLoop;
	uint8_t mbli = pDataParams->sTypeBTargetInfo.sTypeB_I3P4.bMbli;
	uint8_t cid = gphNfcLib_Params.spalI14443p3b.bCid;
	uint8_t len = 1;
	rattrib[0] = (mbli << 4) | cid;
	len += gphNfcLib_Params.spalI14443p3b.wHigherLayerRespLen;
	memcpy(rattrib + 1, gphNfcLib_Params.spalI14443p3b.pHigherLayerResp, gphNfcLib_Params.spalI14443p3b.wHigherLayerRespLen);
	*rlen = len;
	return 0;
}

int Reader_ISO14443_3_Exchange(uint8_t* pTxBuffer, uint16_t wTxBufferLength, uint8_t* pRxBuffer, uint16_t* wRxLength, uint16_t wRxBufferSize, uint16_t timeout){
	phStatus_t	wStatus;
	PH_CHECK_SUCCESS_FCT(wStatus, phhalHw_SetConfig(gphNfcLib_Params.sDiscLoop.pHalDataParams, PHHAL_HW_CONFIG_TIMEOUT_VALUE_US, timeout));
	wStatus = phhalHw_Exchange(
		gphNfcLib_Params.sDiscLoop.pHalDataParams,
		PH_EXCHANGE_DEFAULT,
		(uint8_t *)pTxBuffer,
		wTxBufferLength,
		&gphNfcLib_State.pRxBuffer,
		&gphNfcLib_State.wRxLength);
	if(wStatus){
		LOG_E("error: %04X", wStatus);
		return -1;
	}
	
	if(gphNfcLib_State.wRxLength > wRxBufferSize){
		LOG_E("Over flow!");
		return -2;
	}
	
	memcpy(pRxBuffer, gphNfcLib_State.pRxBuffer, gphNfcLib_State.wRxLength);
	*wRxLength = gphNfcLib_State.wRxLength;
	return 0;
}


